import { injectable, inject, optional } from 'inversify';
import { hredis } from '../../app';
import { IUserService, UserInfo, VERSION_NOW, VERSION_20190430 } from '../api/user';
import { getDateTimeNow, getRandomArbitrary } from '../../util/tools';
import pb = require('../../../gen/pb');

@injectable()
export class UserServiceImpl implements IUserService {
	public static UserKey = (id: string) => `user:${id}`;
	public static UserKeyByPhone = (phone: string) => `user_phone:${phone}`;
	public static UserToken = (token: string) => `token:${token}`;

	CreateDefault(): pb.mb.UserInfo {
		let user = new pb.mb.UserInfo();
		user.videoCanPlay = new pb.mb.CountPair({ current: 0, max: 5 });
		user.audioCanPlay = new pb.mb.CountPair({ current: 0, max: 5 });
		user.novelCanPlay = new pb.mb.CountPair({ current: 0, max: 5 });
		user.name =
			'游客' +
			getRandomArbitrary(1, 9)
				.toString()
				.replace('.', '');

		return user;
	}

	async UpdateUser(id: string, user?: UserInfo): Promise<UserInfo> {
		if (user == null) {
			user = this.CreateDefault();
			user.id = id;
		}
		await hredis.set(UserServiceImpl.UserKey(id), JSON.stringify(user.toJSON(), null, 4));
		if (user.phone != '') {
			await hredis.set(UserServiceImpl.UserKeyByPhone(user.phone), id);
		}
		return user;
	}

	async GetByPhone(phone: string) {
		let id = await hredis.get(UserServiceImpl.UserKeyByPhone(phone));
		if (!id) return null;
		return id;
	}

	async Get(id: string): Promise<UserInfo> {
		if (!(await this.ExistId(id))) return;

		let json = await hredis.get(UserServiceImpl.UserKey(id));

		let ob = JSON.parse(json);
		let user = UserInfo.fromObject(ob);

		// if (!newInfo.VERSION) {
		// 	newInfo = await this.LoadCompatible(newInfo, id);
		// 	console.log('info:======>' + newInfo.VERSION);
		// } else {
		// 	if (newInfo.VERSION != VERSION_NOW) {
		// 		console.log('info:------------>' + newInfo.VERSION);
		// 		newInfo = await this.LoadCompatible(newInfo, id);
		// 	}
		// }

		return user;
	}

	async LoadCompatible(newInfo: UserInfo, id: string): Promise<UserInfo> {
		// if (!newInfo.VERSION) {
		// 	newInfo.VERSION = VERSION_NOW;
		// 	newInfo.changeDate = 0;
		// 	newInfo.dueDate = '';
		// 	newInfo.viewsMaxNums = 5;
		// 	newInfo.serversInfo = '[]';
		// 	await hredis.hmset(
		// 		UserServiceImpl.UserKey(id),
		// 		['VERSION', newInfo.VERSION.toString()],
		// 		['changeDate', newInfo.changeDate.toString()],
		// 		['dueDate', newInfo.dueDate],
		// 		['viewsMaxNums', newInfo.viewsMaxNums.toString()],
		// 		['serversInfo', newInfo.serversInfo],
		// 	);
		// }
		// if (newInfo.VERSION == VERSION_20190430) {
		// 	newInfo.VERSION = VERSION_NOW;
		// 	newInfo.serversInfo = '[]';
		// 	await hredis.hmset(UserServiceImpl.UserKey(id), ['VERSION', newInfo.VERSION.toString()], ['serversInfo', newInfo.serversInfo]);
		// }
		return newInfo;
	}

	async ExistId(id: string) {
		let r = await hredis.exists(UserServiceImpl.UserKey(id));
		return r == 1;
	}

	async ExistPhone(phone: string) {
		let r = await hredis.exists(UserServiceImpl.UserKeyByPhone(phone)).withTimeout(2000);
		return r == 1;
	}

	async IsTokenValid(id: string, token: string) {
		let r = await hredis.exists(UserServiceImpl.UserToken(token));
		if (r) {
			return id == (await hredis.get(UserServiceImpl.UserToken(token)));
		}
		return false;
	}

	async SendVerifyCode(phone: string, code: string) {
		console.log('send sms', phone, code);
	}

	async updateViewNums(id: string, viewsNums: number, changeMax: boolean) {
		let userInfo = await this.Get(id);
		let changeDate = getDateTimeNow();
		if (changeMax) {
			// let viewsMaxNums = userInfo.viewsMaxNums + 1;
			// await hredis.hmset(UserServiceImpl.UserKey(id), ['viewsNums', viewsNums.toString()], ['viewsMaxNums', viewsMaxNums.toString()], ['changeDate', changeDate.toString()]);
		} else {
			await hredis.hmset(UserServiceImpl.UserKey(id), ['viewsNums', viewsNums.toString()], ['changeDate', changeDate.toString()]);
		}

		return true;
	}

	async updateMemberLevel(id: string, userLevel: number, dueDate: string) {
		await hredis.hmset(UserServiceImpl.UserKey(id), ['userLevel', userLevel.toString()], ['dueDate', dueDate]);
		return true;
	}
	async updateServersInfo(id: string, serversInfo: string) {
		await hredis.hmset(UserServiceImpl.UserKey(id), ['serversInfo', serversInfo]);
		return true;
	}
}
